/*
 *     This file is part of Neptune Network Emulator.
 *
 *  Neptune Network Emulator is free software: 
 *  you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Neptune Network Emulator is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Neptune Network Emulator.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
/**
 *
 */
package neptune.web.client.view;

import java.util.LinkedList;
import java.util.List;

import neptune.web.client.WebInterface;
import neptune.web.client.services.ClusterService;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;


/**
 * @author Luigi Lorenzo Arpino [luigiarpino@yahoo.it]
 *
 */
public class PerformanceView extends View
{
	
	public static final String DEFAULT_TOKEN = "Performance";
	public static final int NUM_SAMPLE=5; // numero di campioni
	
	public static final String BLANK_IMG = "img/blank.png";
	private FlexTable pmTable;
	public static final String OK_IMG = "img/ok.png";
	
	// Timeout in secondi
	static final int TIMEOUT = 3;
	private Timer elapsedTimer;
	
	private String idPhysicalMachine;
	
	private HTML graficoRAM;
	private HTML graficoCPUbar;
	private HTML graficoCPUline;
	private List<LinkedList<String>> datiCPU;
	
	private String[] color;
	
	public PerformanceView()
	{
		// Setting view params
		try 
		{
			this.setName(PerformanceView.DEFAULT_TOKEN);
		}
		catch (DuplicatedTokenException e) 
		{
			ConsoleManager.addConsoleDebugMessage(e.getMessage(), true);
		}

		// inizializzo i colori
		 this.color = new String[10];
		 color[0]="0033FF";
		 color[1]="FF0033";
		 color[2]="99FF00";
		 color[3]="FF9933";
		 color[4]="9900CC";
		 color[5]="FFFF00";
		 color[6]="999999";
		 color[7]="000033";
		 color[8]="FF0000";
		 color[9]="000000";
		// Costruzione struttura interfaccia
		VerticalPanel vPanel = new VerticalPanel();
		vPanel.setSize("90%", "100%");

		// Header tabella PM
		FlexTable pmTableHeader = new FlexTable();
		pmTableHeader.setWidth("98%");
		pmTableHeader.setWidget(0, 0, new Image(BLANK_IMG));
		pmTableHeader.setText(0, 1, "Name");
		pmTableHeader.setText(0, 2, "State");
		pmTableHeader.setText(0, 3, "CPU(sec)");
		pmTableHeader.setText(0, 4, "CPU(%)");
		pmTableHeader.setText(0, 5, "MEM(MBs)");
		pmTableHeader.setText(0, 6, "MEM(%)");
		pmTableHeader.setText(0, 7, "MAXMEM(MBs)");
		pmTableHeader.setText(0, 8, "MAXMEM(%)");
		pmTableHeader.setText(0, 9, "VCPUS");
		
		
		pmTableHeader.getColumnFormatter().setWidth(0, "16px");
		pmTableHeader.getColumnFormatter().setWidth(1, "28%");
		pmTableHeader.getColumnFormatter().setWidth(2, "9%");
		pmTableHeader.getColumnFormatter().setWidth(3, "9%");
		pmTableHeader.getColumnFormatter().setWidth(4, "9%");
		pmTableHeader.getColumnFormatter().setWidth(5, "9%");
		pmTableHeader.getColumnFormatter().setWidth(6, "9%");
		pmTableHeader.getColumnFormatter().setWidth(7, "9%");
		pmTableHeader.getColumnFormatter().setWidth(8, "9%");
		pmTableHeader.getColumnFormatter().setWidth(9, "9%");
		
		
		
		
		vPanel.add(pmTableHeader);

		pmTable = new FlexTable();
		pmTable.setWidth("98%");
		ScrollPanel pmTableWrap = new ScrollPanel(pmTable);
		pmTableWrap.setSize("100%", "400px");
		vPanel.add(pmTableWrap);

		
		HorizontalPanel horizontalPanel=new HorizontalPanel();
		this.graficoRAM=new HTML();
		horizontalPanel.add(this.graficoRAM);
		this.graficoCPUbar=new HTML();
		horizontalPanel.add(this.graficoCPUbar);
		this.graficoCPUline=new HTML();
		horizontalPanel.add(this.graficoCPUline);

         
        
		VerticalPanel mainPanel=new VerticalPanel();
		mainPanel.add(horizontalPanel);
		mainPanel.add(vPanel);
		
		initWidget(mainPanel);

		// Styles
		vPanel.setStylePrimaryName("ClusterView");
		pmTableHeader.setStylePrimaryName("ClusterView-pmTable");
		pmTableHeader.addStyleDependentName("header");
		pmTableWrap.setStylePrimaryName("ClusterView-pmTableWrap");
		pmTable.setStylePrimaryName("ClusterView-pmTable");
	
		
		elapsedTimer = new Timer () 
		{
		      public void run() 
		      {
		    	  readDataFromServer();
		      }
		};
	}
	

	
	private void readDataFromServer() 
	{
		ClusterService.Util.getInstance().getXenStatistic(idPhysicalMachine, new AsyncCallback<String[][]>()
		{

			public void onFailure(Throwable caught) 
			{
				String message=new String("Error Unable to read statistic about xen hypervisor: "+caught.getMessage() );
            	WebInterface.addMessageToConsoleAndShowDialog(message,true);
			}

			public void onSuccess(String[][] result) 
			{
				handlerData(result);
			}
		});
	}
	
	
	private void handlerData(String[][] result)
	{
		System.out.println("Data read");
		if (this.datiCPU!=null && this.datiCPU.size() != result.length)
			this.datiCPU=null;
		if (this.datiCPU == null)
		{
			System.out.println("LISTA NULL");
			this.datiCPU = new LinkedList<LinkedList<String>>();
			for(int i=0 ; i <result.length ; i++)
			{
				LinkedList<String> listaCPU=new LinkedList<String>();
				for (int j=0 ; j<NUM_SAMPLE ; j++)
				{
					listaCPU.add("0");
				}
				this.datiCPU.add( listaCPU );
			}
			
		}
		
		String[] nomiDomini=new String[result.length];
		String[] ram=new String[result.length];
		String[] cpuPerc=new String[result.length];
		int row = pmTable.getRowCount();
		for (int i=0 ; i<row ;i++)
		{
			pmTable.removeRow(0);
		}
		for (int i=0 ; i<result.length ;i++)
		{
			pmTable.setWidget(i, 0, new DomainNodePanel(result[i][0],result[i][1],result[i][2],
					result[i][3],result[i][4],result[i][5],result[i][6],
					result[i][7],result[i][8]));
			nomiDomini[i]=result[i][0];
			cpuPerc[i]=result[i][3];
			ram[i]=result[i][4];
		}
		
		for(int i=0 ; i <result.length ; i++)
		{
			List<String> list =(List<String>)this.datiCPU.get(i);
			list.add( String.valueOf( Double.valueOf(cpuPerc[i]).intValue()  ) );
			if (list.size() > NUM_SAMPLE )
				list.remove(0);
		}
		System.out.println("this.datiCPU.toString()--> "+this.datiCPU.toString() );
		
		this.setRamChart(nomiDomini, ram);
		this.setCPUbarChart(nomiDomini, cpuPerc);
		this.setCPUlineChart(nomiDomini, cpuPerc);
		SuperView view =  (SuperView)ViewManager.getViewManager().getActiveView();
		String nameView = view.getActiveView().getName();
		if ( nameView.equalsIgnoreCase( PerformanceView.DEFAULT_TOKEN ) )
		{
			System.out.println("rilancio il TIMER");
			this.elapsedTimer.schedule(TIMEOUT *1000);
		}
		else
		{
			System.out.println("fermo il timer");
			this.datiCPU= null;
		}
		System.out.println("activeView.getName()->" +nameView  );
	}
	
	private void setCPUlineChart(String[] nomiDomini, String[] cpuPerc)
	{
		String html="<html><body>" +
		"<img src='"+GWT.getModuleBaseURL()+"chart?"+
		"cht=lc"+ // tipo
		"&amp;chs=400x150"+ // dimensioni del grafico
		"&amp;chtt=CPU+usage+history"+//titolo
		"&amp;chg=25,25,5,5"+// griglia
		"&amp;chxt=y"+ // mostra valori su asse Y
		//"&amp;chco=FF0000,0000FF"; // colori
		"&amp;chco=";
		for (int i=0;i<nomiDomini.length ; i++)
		{
			html += this.color[i%this.color.length];
			if (i+1 != nomiDomini.length )
				html += ",";
		}
		//"&amp;chdl=Dom0|DomU|"+ // nomi domini
		html += "&amp;chdl=";
		for (int i=0;i<nomiDomini.length ; i++)
		{
			//html+=nomiDomini[nomiDomini.length-i-1];
			html+=nomiDomini[i];
			if (i+1 != nomiDomini.length)
				html += "|";
		}
		//html=html+="&amp;chd=t:10,50,60,80,40|50,60,100,40,20' />"; //dati
		html += "&amp;chd=t:";
		
		for (int i=0;i<nomiDomini.length ; i++)
		{
			List<String> lista = (List<String>)this.datiCPU.get(i);
			for (int j=0 ; j<lista.size() ; j++)
			{
				html=html+=lista.get(j);
					if (j+1 != lista.size() )
						html += ",";
			}
			if (i+1 != nomiDomini.length)
				html += "|";
		}
		
		html=html+="' /></body></html>";
		System.out.println("--> "+html);
		this.graficoCPUline.setHTML(html);
	}
	
	private void setCPUbarChart(String[] nomiDomini, String[] cpuPerc)
	{
		int altezzaGrafico=50 + cpuPerc.length*40;
		if (altezzaGrafico < 150)
			altezzaGrafico=150;
		String html="<html><body>" +
		"<img src='"+GWT.getModuleBaseURL()+"chart?"+
		"chs=350x"+String.valueOf(altezzaGrafico)+
		//"&amp;cht=bhs"+ // tipo di grafico
		"&amp;cht=bhs3"+ // tipo di grafico
		"&amp;chtt=CPU+usage+average"+ // titolo
		"&amp;chco=FF0000"+ // colore
		"&amp;chxt=x,y"; // disegna asse x e y
		//
		int[] value=new int[cpuPerc.length];
		// inizializzo
		for (int j=0 ; j<cpuPerc.length ; j++)
		{
			value[j]=0;
		}
		// leggo i valori
		for (int i=0 ; i<cpuPerc.length ; i++)
		{
			List<String> lista = (List<String>)this.datiCPU.get(i);
			for (int j=0 ; j<lista.size() ; j++)
			{
				value[i] += Double.valueOf( lista.get(j) ).intValue() ;
			}
		}
		// calcolo le medie e scrivo i valori
		html +="&amp;chd=t:";
		for (int i=0;i<cpuPerc.length ; i++)
		{
			value[i]=value[i]/((List<String>)this.datiCPU.get(i)).size();
			html+=value[i];
			if (i+1 != cpuPerc.length)
				html += ",";
		}
		html+="&amp;chxl=0:|0|25|50|100|1:|";// asse x y
		/*
		for (int i=0;i<nomiDomini.length ; i++)
		{
			html+=nomiDomini[nomiDomini.length-i-1];
			if (i+1 != nomiDomini.length)
				html += "|";
		}
		*/
		// scrivo i nomi
		for (int i=0;i<nomiDomini.length ; i++)
		{
			html+=nomiDomini[nomiDomini.length-i-1];
			if (i+1 != nomiDomini.length)
				html += "|";
		}
		//
		html+="'alt='CPU Usage' /></body></html>";
		System.out.println("***>>> "+html);
		this.graficoCPUbar.setHTML(html);
	}
	
	private void setRamChart(String[] nomiDonmini, String[] ram)
	{
		// Aggiusto la ram
		int ramTOT=0;
		for (int i=0 ;i< ram.length ;i++)
		{
			ramTOT += Integer.valueOf(ram[i]).intValue();
		}
		for (int i=0 ;i< ram.length ;i++)
		{
			ram[i]=String.valueOf( (Integer.valueOf(ram[i]).intValue()*100) / ramTOT );
		}
		String html="<html><body>" +
			"<img src='"+GWT.getModuleBaseURL()+"chart?"+
		"chs=350x150"+
		"&amp;chd=t:";
		for (int i=0;i<ram.length ; i++)
		{
			html+=ram[i];
			if (i+1 != ram.length)
				html += ",";
		}
		html+="&amp;cht=p3"+// tipo di grafico
		"&amp;chco=0000ff"+// COLORE
		"&amp;chtt=RAM+usage"+// TITOLO
		"&amp;chl=";
		for (int i=0;i<nomiDonmini.length ; i++)
		{
			html+=nomiDonmini[i];
			if (i+1 != nomiDonmini.length)
				html += "|";
		}
		html+="'alt='RAM distribution' /></body></html>";
		this.graficoRAM.setHTML(html);
	}
	

	
	public void startPollingToServer()
	{
		System.out.println("Faccio partire il timer");
		this.datiCPU=null;
		readDataFromServer();
	}
	

	
	public void setIdPhysicalMachine(String idPhysicalMachine)
	{
		this.idPhysicalMachine=idPhysicalMachine;
	}
	
	

	
	public class DomainNodePanel extends Composite
	{
	
		public DomainNodePanel(String name, String state, String cpuSec, String cpuPer, String mem,
				String memPerc, String maxMem, String maxMemPerc, String vcpus)
		{
			
			
			VerticalPanel vPanel = new VerticalPanel();
			vPanel.setSize("100%", "100%");
	
			FlexTable dataTable = new FlexTable();
			dataTable.setWidth("100%");
			Image img = new Image(OK_IMG);
			//img.setTitle(descrizione);
			dataTable.setWidget(0, 0, img);
			dataTable.setText(0, 1, name);
			dataTable.setText(0, 2, state);
			dataTable.setText(0, 3, cpuSec);
			dataTable.setText(0, 4, cpuPer);
			dataTable.setText(0, 5, mem);
			dataTable.setText(0, 6, memPerc);
			dataTable.setText(0, 7, maxMem);
			dataTable.setText(0, 8, maxMemPerc);
			dataTable.setText(0, 9, vcpus);
			
		
			dataTable.getColumnFormatter().setWidth(0, "16px");
			dataTable.getColumnFormatter().setWidth(1, "28%");
			dataTable.getColumnFormatter().setWidth(2, "9%");
			dataTable.getColumnFormatter().setWidth(3, "9%");
			dataTable.getColumnFormatter().setWidth(4, "9%");
			dataTable.getColumnFormatter().setWidth(5, "9%");
			dataTable.getColumnFormatter().setWidth(6, "9%");
			dataTable.getColumnFormatter().setWidth(7, "9%");
			dataTable.getColumnFormatter().setWidth(8, "9%");
			dataTable.getColumnFormatter().setWidth(9, "9%");
			

			
			vPanel.add(dataTable);
	
			initWidget(vPanel);
			// Styles
			vPanel.setStylePrimaryName("ClusterView-NodePanel");
			dataTable.setStylePrimaryName("ClusterView-NodePanel-dataTable");
		}
	}

	
	

	
}
